package com.eliza.base.broadcast

import android.Manifest
import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat

//Broadcast(广播)机制是Android四大组件之一，在四大组件的另外两个组件Activity和Service拥有发送和接收广播的能力
//Android广播机制是在Binder进程间通信机制的基础上实现的，内部基于消息发布和订阅的事件驱动模型，广播发送者负责发送消息，广播接收者需要先订阅消息，然后才能收到消息

const val MyBroadcastReceiverPackage = "com.eliza.base.broadcast"
const val VOLUME_CHANGED_ACTION: String = "android.media.VOLUME_CHANGED_ACTION" //音量
private const val TAG = "Tag:com.eliza.base.broadcast.BroadcastReceiver"

val BroadcastReceiverReceiver = IntentFilter(Intent.ACTION_SCREEN_ON).apply {
    addAction(Intent.ACTION_SCREEN_OFF)
    addAction(Intent.ACTION_SCREEN_ON)
    addAction(VOLUME_CHANGED_ACTION)
    addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
}

//因为在广播中是不允许开辟线程的, 当onReceiver( )方法运行较长时间(超过10秒)还没有结束的话,那么程序会报错(ANR)
//广播更多的时候扮演的是一个打开其他组件的角色,

class MyBroadcastReceiver() : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        /*
        * 接受xml 配置的所有篩選條件
        * */
        StringBuilder().apply {
            append("Action: ${intent.action}\n")
            append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
            append("DATA: ${intent.getStringExtra("data")}\n")
            toString().let { log ->
                Log.d(TAG, log)
            }
        }
        if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.BLUETOOTH_CONNECT
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            Log.e(TAG, "BluetoothAdapter checkSelfPermission Err")
            return
        }
        context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
    }
}


class BroadcastSender(val activity: Activity) {
    //要注册本地广播，请调用 LocalBroadcastManager.registerReceiver(BroadcastReceiver, IntentFilter)。
    fun register(activity: Activity, receiver: BroadcastReceiver) {
//    创建 IntentFilter 并调用 registerReceiver(BroadcastReceiver, IntentFilter) 来注册接收器

//        Apps targeting Android 7.0 (API level 24) and higher do not receive this broadcast
//        if they declare the broadcast receiver in their manifest.
//        Apps will still receive broadcasts if they register their
//        android.content.BroadcastReceiver with Context.registerReceiver() and that context is still valid.

        val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
            addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
        }
        activity.registerReceiver(receiver, filter)
        // 帶權限註冊
        activity.registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null)
        activity.unregisterReceiver(receiver)
//    如果您使用 Activity 上下文在 onCreate(Bundle) 中注册接收器，则应在 onDestroy() 中注销，以防接收器从 Activity 上下文中泄露出去。
//    如果您在 onResume() 中注册接收器，则应在 onPause() 中注销，以防多次注册接收器（如果您不想在暂停时接收广播，这样可以减少不必要的系统开销）。
//    请勿在 onSaveInstanceState(Bundle) 中注销，因为如果用户在历史记录堆栈中后退，则不会调用此方法。
    }
    /*
    * Android 为应用提供三种方式来发送广播：

    sendOrderedBroadcast(Intent, String) 方法一次向一个接收器发送广播。当接收器逐个顺序执行时，接收器可以向下传递结果，也可以完全中止广播，使其不再传递给其他接收器。接收器的运行顺序可以通过匹配的 intent-filter 的 android:priority 属性来控制；具有相同优先级的接收器将按随机顺序运行。
    sendBroadcast(Intent) 方法会按随机的顺序向所有接收器发送广播。这称为常规广播。这种方法效率更高，但也意味着接收器无法从其他接收器读取结果，无法传递从广播中收到的数据，也无法中止广播。
    LocalBroadcastManager.sendBroadcast 方法会将广播发送给与发送器位于同一应用中的接收器。如果您不需要跨应用发送广播，请使用本地广播。这种实现方法的效率更高（无需进行进程间通信），而且您无需担心其他应用在收发您的广播时带来的任何安全问题。
    * */

    fun send(action: String) {
        //發送
//    收器的运行顺序可以通过匹配的 intent-filter 的 android:priority 属性来控制；具有相同优先级的接收器将按随机顺序运行。
        Intent().also { intent ->
            intent.setAction(action)
            intent.putExtra("data", "Notice me senpai!")
            activity.sendBroadcast(intent)
        }
//    广播消息封装在 Intent 对象中。
//    Intent 的操作字符串必须提供应用的 Java 软件包名称语法，并唯一标识广播事件。您可以使用 putExtra(String, Bundle) 向 intent 附加其他信息。您也可以对 intent 调用 setPackage(String)，将广播限定到同一组织中的一组应用。
    }

    //    Manifest.permission.SEND_SMS
    fun sendWithPermission(action: String, receiverPermission: String) {
        activity.sendBroadcast(Intent(action), receiverPermission)
    }
}